; 实验15 安装新的int9中断例程
; 功能：DOS下，按下A键后，除非不再松开，如果松开将显示满屏的A,其他键照常处理
assume cs:codesg,ds:datasg,ss:stacksg
stacksg segment
    db 128 dup(0)
stacksg ends

codesg segment
start:
        mov ax,stacksg
        mov ss,ax
        mov sp,128
        
        push cs
        pop es
        mov di,offset nint9
        
        mov ax,0
        mov ds,ax
        mov si,206h
        ; 复制int9程序数据从206h开始
        mov cx,offset nint9end - offset nint9
        cld
        rep  movsb

        ; 缓存原int9中断例程入口地址到0000:200h-202h
        push ds:[9*4]
        pop ds:[200h]
        push ds:[9*4+2]
        pop ds:[202h]
        ; 0000:204h记录A是否已按下，此次先置0-未按下
        mov word ptr ds:[204h],0
        ; 设置指向新位置
        cli
        mov word ptr ds:[9*4],206h
        mov word ptr ds:[9*4+2],0h
        sti
        ; 安装程序退出
        mov ax,4c00h
        int 21h
nint9:
        push ax
        push bx
        push es
        push cs
        pop es
        in al,60h
        pushf
        call dword ptr es:[200h]
        cmp al,01eh
        call adown
        cmp al,01eh+80h
        call aup
        jmp short nint9OK
; A键按下，记录到0000:204h位置1
adown:
        push ds
        push cs
        pop ds
        cmp byte ptr ds:[204h],1
        je adend
        mov byte ptr ds:[204h],1
adend:  pop ds
        ret
; A键抬起，检测0000:204h是否为1
aup:
        push ds
        push cs
        pop ds
        cmp byte ptr ds:[204h],1
        je fulla
        mov byte ptr ds:[204h],0
        pop ds
        ret
; 显示全屏A
fulla:
        push bx
        push cx
        push ds
        mov bx,0b800h
        mov ds,bx
        mov bx,0
        mov cx,2000
s:      mov byte ptr ds:[bx],'A'
        add bx,2
        loop s
        pop ds
        pop cx
        pop bx
        ret
; 新中断例程退出
nint9OK:
        pop es
        pop bx
        pop ax
        iret
nint9end:nop

codesg ends

end start